/**
 * 
 */
package org.whereiswally.recognition.imp.faint;

import java.io.File;
import java.io.FileOutputStream;
import java.io.Serializable;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.whereiswally.WallyConstants;
import org.whereiswally.model.Wally;
import org.whereiswally.model.WallyFace;
import org.whereiswally.net.picturerepository.PictureRepository;
import org.whereiswally.recognition.FaceRecognition;

import de.offis.faint.controller.MainController;
import de.offis.faint.model.ImageModel;
import de.offis.faint.model.Region;

/**
 * @author lgiavedoni
 * 
 */
public class FaintFaceRecognition implements FaceRecognition, Serializable {

    private static Logger logger = Logger.getLogger(FaintFaceRecognition.class);

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.whereiswally.recognition.FaceRecognition#tryRecognition(org.whereiswally
     * .model.Wally)
     */
    public List<WallyFace> tryRecognition(Wally wally, List<URI> pictures) {
	List<WallyFace> result = new ArrayList<WallyFace>();
	try {
	    MainController mc = MainController.getInstance();

	    // eliminamos las posibles caras de la BD
	    if (mc.getFaceDB().getRegionsForFace(wally.getName()) != null)
		for (Region reg : mc.getFaceDB().getRegionsForFace(
			wally.getName())) {
		    mc.getFaceDB().deleteRegion(reg);
		}

	    File faceF;
	    for (byte[] faceB : wally.getFaces()) {
		faceF = new File(WallyConstants.TMP_DIR + wally.getName());
		IOUtils.write(faceB, new FileOutputStream(faceF));

		ImageModel im = new ImageModel(faceF);
		im.getImage(true);
		Region[] reg = mc.detectFaces(im, false);
		if (reg == null || reg.length == 0)
		    logger.error("No se ha detectado ninguna cara para: "
			    + wally.getName());
		else {
		    if (reg.length > 1)
			logger.warn("Se ha detectado mas de una cara para: "
				+ wally.getName()
				+ ", se tomara la 0 para el reconocimiento");
		    Region reg0 = reg[0];
		    mc.getFaceDB().put(reg0, wally.getName());
		}
		faceF.delete();
	    }

	    // Procesamos las fotos donde pueda estar nuestro wally
	    for (URI uri : pictures) {
		File picture = PictureRepository.downloadPicture(uri);
		ImageModel im = new ImageModel(picture);
		im.getImage(true);
		// TODO: modificar para que se empleen distions algoritmos(.xml)
		// de reconocimientos de rostros
		Region[] reg = mc.detectFaces(im, false);

		// Para cada cara de la foto intentamos verificar si es wally
		if (reg != null)
		    for (int i = 0; i < reg.length; i++) {
			result.add(new WallyFace(uri, i, mc.recognizeFace(
				reg[i]).get(wally.getName())));
		    }
		picture.delete();
	    }

	} catch (Exception e) {
	    // TODO: notificar del error al SRV
	    logger.error(e);
	}
	// Sort faces
	Collections.sort(result);

	return result;
    }
}
